﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the BBCode helper.
    /// </summary>
    public static class BBCodeHelper
    {
        #region Constants

        private static readonly Dictionary<Regex, String> BBCode2Html = new Dictionary<Regex, String>
        {
            {new Regex(@"\[br\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<br/>"},
            {new Regex(@"\[b\](.+?)\[/b\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<b>$1</b>"},
            {new Regex(@"\[i\](.+?)\[/i\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<i>$1</i>"},
            {new Regex(@"\[u\](.+?)\[/u\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<u>$1</u>"},
            {new Regex(@"\[s\](.+?)\[/s\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<s>$1</s>"},
            {new Regex(@"\[p\](.+?)\[/p\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<p>$1</p>"},
            {new Regex(@"\[h1\](.+?)\[/h1\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h1>$1</h1>"},
            {new Regex(@"\[h2\](.+?)\[/h2\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h2>$1</h2>"},
            {new Regex(@"\[h3\](.+?)\[/h3\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h3>$1</h3>"},
            {new Regex(@"\[h4\](.+?)\[/h4\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h4>$1</h4>"},
            {new Regex(@"\[h5\](.+?)\[/h5\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h5>$1</h5>"},
            {new Regex(@"\[h6\](.+?)\[/h6\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<h6>$1</h6>"},
            {new Regex(@"\[url\=([^\]]+)\](.+?)\[/url\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<a href=\"$1\" rel=\"nofollow\">$2</a>"},
            {new Regex(@"\[img](.+?)\[/img\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<img src=\"$1\" />"},
            {new Regex(@"\[code\=([^\]]+)\](.+?)\[/code\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<code class=\"$1\">$2</code>"},
            {new Regex(@"\[size\=([\d]+)\](.+?)\[/size\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<font style=\"font-size: $1%\">$2</font>"},
            {new Regex(@"\[quote\=([^\]]+)\](.+?)\[/quote\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<blockquote><cite>$1</cite>$2</blockquote>"},
            {new Regex(@"\[list\=([\d]+)\](.+?)\[/list\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<ol start=\"$1\">$2</ol>"},
            {new Regex(@"\[list\](.+?)\[/list\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<ul>$1</ul>"},
            {new Regex(@"\[li\](.+?)\[/li\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "<li>$1</li>"}
        };

        private static readonly Dictionary<Regex, String> BBCode2PlainText = new Dictionary<Regex, String>
        {
            {new Regex(@"\[br\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n"},
            {new Regex(@"\[b\](.+?)\[/b\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[i\](.+?)\[/i\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[u\](.+?)\[/u\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[s\](.+?)\[/s\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[p\](.+?)\[/p\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n$1\n"},
            {new Regex(@"\[h1\](.+?)\[/h1\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[h2\](.+?)\[/h2\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[h3\](.+?)\[/h3\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[h4\](.+?)\[/h4\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[h5\](.+?)\[/h5\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[h6\](.+?)\[/h6\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[url\=([^\]]+)\](.+?)\[/url\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$2($1)"},
            {new Regex(@"\[img](.+?)\[/img\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$1"},
            {new Regex(@"\[code\=([^\]]+)\](.+?)\[/code\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n$2\n"},
            {new Regex(@"\[size\=([\d]+)\](.+?)\[/size\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "$2"},
            {new Regex(@"\[quote\=([^\]]+)\](.+?)\[/quote\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n$1:\n$2\n"},
            {new Regex(@"\[list\=([\d]+)\](.+?)\[/list\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n$2\n"},
            {new Regex(@"\[list\](.+?)\[/list\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "\n$1\n"},
            {new Regex(@"\[li\](.+?)\[/li\]", RegexOptions.Compiled | RegexOptions.IgnoreCase), "- $1\n"}
        };

        #endregion

        #region Methods

        /// <summary>
        /// Converts the BBCode string to the HTML string.
        /// </summary>
        /// <param name="s">The input string.</param>
        /// <returns>The HTML string.</returns>
        public static string ToHtml(string s)
        {
            if(String.IsNullOrEmpty(s))
                return s;

            string res = s;
            res = HtmlUtility.FromPlainText(res);

            foreach(var i in BBCode2Html)
            {
                res = i.Key.Replace(res, i.Value);
            }
            return res;
        }

        /// <summary>
        /// Removes all BBCode tags.
        /// </summary>
        /// <param name="s">The input string.</param>
        /// <returns>The result string.</returns>
        public static string StripTags(string s)
        {
            if(String.IsNullOrEmpty(s))
                return s;

            string res = s;

            foreach(var i in BBCode2PlainText)
            {
                res = i.Key.Replace(res, i.Value);
            }
            return res;
        }

        /// <summary>
        /// Quotes the input string.
        /// </summary>
        /// <param name="s1">The name of an author.</param>
        /// <param name="s2">The input string.</param>
        /// <returns>The quoted string.</returns>
        public static string Quote(string s1, string s2)
        {
            return String.Format("[quote={0}]{1}[/quote]", s1, s2);
        }

        #endregion
    }
}
